use crate::modules::database::{Database, Menu};
use crate::modules::interfaces::{MenuInterface, ApiResponse};
use anyhow::Result;
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;

#[derive(Debug, Serialize, Deserialize)]
pub struct CreateMenuRequest {
    pub parent_id: Option<i32>,
    pub menu_name: String,
    pub menu_path: Option<String>,
    pub menu_icon: Option<String>,
    pub menu_type: String,
    pub sort_order: i32,
    pub is_visible: bool,
    pub permissions: serde_json::Value,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct UpdateMenuRequest {
    pub menu_name: Option<String>,
    pub menu_path: Option<String>,
    pub menu_icon: Option<String>,
    pub menu_type: Option<String>,
    pub sort_order: Option<i32>,
    pub is_visible: Option<bool>,
    pub permissions: Option<serde_json::Value>,
}

pub struct MenuManagement {
    db: Database,
}

impl MenuManagement {
    pub fn new(db: Database) -> Self {
        Self { db }
    }

    pub fn create_menu(&self, request: CreateMenuRequest) -> Result<ApiResponse<MenuInterface>> {
        let now = OffsetDateTime::now_utc();
        
        let menu = Menu {
            id: 0,
            parent_id: request.parent_id,
            menu_name: request.menu_name,
            menu_path: request.menu_path,
            menu_icon: request.menu_icon,
            menu_type: request.menu_type,
            sort_order: request.sort_order,
            is_visible: request.is_visible,
            permissions: request.permissions,
            created_at: now,
            updated_at: now,
        };

        let menu_id = self.db.add_menu(menu);
        
        // 获取菜单信息并转换为接口类型
        let menu = self.db.get_menu(menu_id).ok_or(anyhow::anyhow!("菜单创建失败"))?;
        let menu_interface = self.convert_to_menu_interface(menu)?;
        
        Ok(ApiResponse::success(menu_interface))
    }

    pub fn get_menu(&self, id: i32) -> Result<ApiResponse<Option<MenuInterface>>> {
        if let Some(menu) = self.db.get_menu(id) {
            let menu_interface = self.convert_to_menu_interface(menu)?;
            Ok(ApiResponse::success(Some(menu_interface)))
        } else {
            Ok(ApiResponse::success(None))
        }
    }

    pub fn update_menu(&self, id: i32, request: UpdateMenuRequest) -> Result<ApiResponse<MenuInterface>> {
        let mut menu = self.db.get_menu(id).ok_or(anyhow::anyhow!("菜单不存在"))?;
        let now = OffsetDateTime::now_utc();

        if let Some(menu_name) = request.menu_name {
            menu.menu_name = menu_name;
        }
        if let Some(menu_path) = request.menu_path {
            menu.menu_path = Some(menu_path);
        }
        if let Some(menu_icon) = request.menu_icon {
            menu.menu_icon = Some(menu_icon);
        }
        if let Some(menu_type) = request.menu_type {
            menu.menu_type = menu_type;
        }
        if let Some(sort_order) = request.sort_order {
            menu.sort_order = sort_order;
        }
        if let Some(is_visible) = request.is_visible {
            menu.is_visible = is_visible;
        }
        if let Some(permissions) = request.permissions {
            menu.permissions = permissions;
        }
        menu.updated_at = now;

        if !self.db.update_menu(id, menu) {
            return Err(anyhow::anyhow!("菜单更新失败"));
        }

        // 直接获取更新后的菜单并转换为接口类型
        let updated_menu = self.db.get_menu(id).ok_or(anyhow::anyhow!("菜单更新后获取失败"))?;
        let menu_interface = self.convert_to_menu_interface(updated_menu)?;
        Ok(ApiResponse::success(menu_interface))
    }

    pub fn delete_menu(&self, id: i32) -> Result<ApiResponse<bool>> {
        let result = self.db.delete_menu(id);
        Ok(ApiResponse::success(result))
    }

    pub fn list_menus(&self) -> Result<ApiResponse<Vec<MenuInterface>>> {
        let all_menus = self.db.get_all_menus();
        let mut menu_interfaces = Vec::new();
        
        for menu in all_menus {
            let menu_interface = self.convert_to_menu_interface(menu)?;
            menu_interfaces.push(menu_interface);
        }

        Ok(ApiResponse::success(menu_interfaces))
    }

    pub fn get_menu_tree(&self) -> Result<ApiResponse<Vec<MenuTreeNode>>> {
        let all_menus = self.db.get_all_menus();
        let mut tree = Vec::new();
        
        // 构建菜单树
        for menu in &all_menus {
            if menu.parent_id.is_none() {
                tree.push(self.build_menu_node(menu, &all_menus));
            }
        }
        
        Ok(ApiResponse::success(tree))
    }

    fn convert_to_menu_interface(&self, menu: Menu) -> Result<MenuInterface> {
        Ok(MenuInterface {
            id: menu.id,
            parent_id: menu.parent_id,
            menu_name: menu.menu_name,
            menu_path: menu.menu_path,
            menu_icon: menu.menu_icon,
            menu_type: menu.menu_type,
            sort_order: menu.sort_order,
            is_visible: menu.is_visible,
            permissions: menu.permissions,
            created_at: menu.created_at,
        })
    }

    fn build_menu_node(&self, menu: &Menu, all_menus: &[Menu]) -> MenuTreeNode {
        let mut children = Vec::new();
        
        for child_menu in all_menus {
            if child_menu.parent_id == Some(menu.id) {
                children.push(self.build_menu_node(child_menu, all_menus));
            }
        }
        
        MenuTreeNode {
            id: menu.id,
            menu_name: menu.menu_name.clone(),
            menu_path: menu.menu_path.clone(),
            menu_icon: menu.menu_icon.clone(),
            menu_type: menu.menu_type.clone(),
            sort_order: menu.sort_order,
            is_visible: menu.is_visible,
            permissions: menu.permissions.clone(),
            children,
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct MenuTreeNode {
    pub id: i32,
    pub menu_name: String,
    pub menu_path: Option<String>,
    pub menu_icon: Option<String>,
    pub menu_type: String,
    pub sort_order: i32,
    pub is_visible: bool,
    pub permissions: serde_json::Value,
    pub children: Vec<MenuTreeNode>,
}